package com.example.demo.utils;


import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.databind.module.SimpleModule;
import org.apache.commons.lang3.StringUtils;
import org.json.JSONObject;

import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;


public class JSONUtil {

    private static final ObjectMapper objectMapper = new ObjectMapper() {{
        configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
        configure(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES, true);
        configure(MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES, true);
        configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
        SimpleModule sm = new SimpleModule();
        registerModule(sm);
    }};

    public static String toJson(Object instance) throws IOException {
        if (instance == null) {
            return null;
        }
        return objectMapper.writeValueAsString(instance);
    }

    /**
     *
     * @param instance
     * @param dateFormat 日期格式转为String自定义format,如yyyy-MM-dd等
     * @return
     * @throws IOException
     */
    public static String toJson(Object instance, String dateFormat) throws IOException {
        if (instance == null) {
            return null;
        }
        objectMapper.setDateFormat(new SimpleDateFormat(dateFormat));
        return objectMapper.writeValueAsString(instance);
    }

    /**
     * 反序列化json为Map
     *
     * @param json
     * @return
     * @throws IOException
     */
    public static Map<String, Object> toMap(String json) throws IOException {
        if (StringUtils.isBlank(json)) {
            return Collections.EMPTY_MAP;
        }
        return objectMapper.readValue(json, HashMap.class);
    }

    /**
     * 反序列化json字符串为指定类型的实例
     *
     * @param json
     * @param clazz
     * @param <T>
     * @return
     * @throws IOException
     */
    public static <T> T toInstance(String json, Class<T> clazz) throws IOException {
        if (StringUtils.isBlank(json)) {
            return null;
        }
        return objectMapper.readValue(json, clazz);
    }

    /**
     * 反序列化json字符串为指定类型的实例的list
     *
     * @param json
     * @param clazz
     * @param <T>
     * @return
     * @throws IOException
     */
    public static <T> List<T> toInstanceList(String json, Class<T> clazz) throws IOException {
        if (StringUtils.isBlank(json)) {
            return null;
        }
        return objectMapper.readValue(json, getCollectionType(List.class, clazz));
    }

    /**
     * 获取泛型的Collection Type
     *
     * @param collectionClass 泛型的Collection
     * @param elementClasses  实体bean
     * @return JavaType Java类型
     */
    private static JavaType getCollectionType(Class<?> collectionClass, Class<?>... elementClasses) {
        return objectMapper.getTypeFactory().constructParametricType(collectionClass, elementClasses);
    }

    /**
     * 将Map转化为指定类型的实例
     *
     * @param map
     * @param tClass
     * @param <T>
     * @return
     * @throws IOException
     */
    public static <T> T mapToInstance(Map map, Class<T> tClass) throws IOException {
        return objectMapper.readValue(toJson(map), tClass);
    }

    /**
     * 可以是用替代方法 com.ctrip.ops.ehrms.common.util.JSONUtil#toInstanceList(java.lang.String, java.lang.Class)<br/>
     * <p>
     * 反序列化json字符串为指定TypeReference声明的类型
     *
     * @param json
     * @param typeReference
     * @param <T>
     * @return
     * @throws IOException
     */
    @Deprecated
    public static <T> T parse(String json, TypeReference<T> typeReference) throws IOException {
        if (StringUtils.isBlank(json)) {
            return null;
        }
        return objectMapper.readValue(json, typeReference);
    }

    /**
     * 适配之前fastjson的parseObject。小改动替换fastjson。
     *
     * @param json
     * @returnAssertionHolder
     * @throws IOException
     */
    public static JSONObject parseObject(String json) throws IOException {
        if (StringUtils.isBlank(json)) {
            return new JSONObject();
        }
        return objectMapper.readValue(json, JSONObject.class);
    }

    /**
     * 适配之前fastjson的parseArray。小改动替换fastjson。
     *
     * @param json
     * @return
     * @throws IOException
     */
    public static JSONArray parseArray(String json) throws IOException {
        if (StringUtils.isBlank(json)) {
            return new JSONArray();
        }
        return objectMapper.readValue(json, JSONArray.class);
    }

    /**
     * 获取json中的某个值
     *
     * @param json
     * @param key
     * @return
     */
    public static String getValue(String json, String key) throws JsonProcessingException {
        if (StringUtils.isBlank(json)) return "";
        return objectMapper.readTree(json).get(key).asText();
    }
}
